/***************************************************************
*  Copyright (c) 2007 by GroupMe! Team (www.groupme.net)
*  All rights reserved.
*
*  This file is part of the GroupMe! Project. Source code of 
*  this project is closed and redistribution of this code is
*  prohibited. 
*  
*  Contact: http://www.groupme.net
*
*  This copyright notice MUST APPEAR in all copies of the file!
***************************************************************/
package net.groupme.search.strategy.folkrank;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;

import net.groupme.model.ObjectFactory;
import net.groupme.search.strategy.model.TAS;
import net.groupme.search.strategy.model.TASImpl;
import cern.colt.matrix.impl.SparseDoubleMatrix2D;

/**
 * created on 16 Jan 2008
 * 
 * This class extends the Normal FolkRank approach. It propagates group tags to their resources, resource tags to other resources, 
 * and performs a normal FolkRank afterwards.
 * 
 * @author Fabian Abel, <a href="mailto:abel@l3s.de">abel@l3s.de</a>
 * @author last edited by: $Author: fabian $
 * 
 * @version $Revision: 1.1 $ $Date: 2008-01-17 02:58:58 $
 */
public class NormalFolkRankWithFullTagPropagation extends NormalFolkRankRankingStrategy{

	/**
	 * Creates a new NormalFolkRankWithFullTagPropagation instance. 
	 */
	public NormalFolkRankWithFullTagPropagation() {
		super();
	}
	
	/* (non-Javadoc)
	 * @see net.groupme.search.strategy.folkrank.NormalFolkRankRankingStrategy#getName()
	 */
	@Override
	public String getName() {
		return "FolkRank + Full Propagation";
	}

	/* (non-Javadoc)
	 * @see net.groupme.search.strategy.folkrank.NormalFolkRankRankingStrategy#getDescription()
	 */
	@Override
	public String getDescription() {
		return "Propagates group tags to their resources, resource tags to other resources, and performs a normal FolkRank afterwards";
	}
	

	/* (non-Javadoc)
	 * @see net.groupme.search.strategy.folkrank.NormalFolkRankRankingStrategy#constructAdjacencyMatrix()
	 */
	@Override
	protected void constructAdjacencyMatrix(){
		/* 1. Gather data: */
		Statement sqlStatement = null;
		ResultSet result = null;
		List<TAS> tagAssignments = null;
		
		try {
			sqlStatement = ObjectFactory.ds.getConnection().createStatement();
		
			tagAssignments = addNormalMappings(sqlStatement);	
			
			//propagate group tags:
			result = sqlStatement.executeQuery("Select a.userId, a.tagId, b.resourceId, a.resourceId from userTagGroupResource as a, groupResource as b where a.resourceId = b.groupId AND a.groupId is NULL ");
			TAS actualTas = null;
			while(result.next()){
				actualTas = new TASImpl(result.getInt(1), result.getInt(2),result.getInt(3),result.getInt(4));
				actualTas.setDirectTAS(false);
				tagAssignments.add(actualTas);	
				//nur (ungetaggte) resourcen koennen dazukommen 
				if(!resourceIdColumMapping.containsKey(actualTas.getResourceId())){
					resourceIdColumMapping.put(actualTas.getResourceId(), position);
					position++;
				}
			}
			//propagate tags of resources to their neighbour resources:
			result = sqlStatement.executeQuery("Select newTas.user, newTas.tag, gr.resourceId, newTas.groupId FROM " +
					"(Select tas.userId as user, tas.tagId as tag, tas.resourceId as resource, g.groupId as groupId FROM " +
						"(Select a.userId, a.tagId, a.resourceId from userTagGroupResource as a, Tag as t WHERE t.id = a.tagId) as tas, groupResource as g WHERE g.resourceId = tas.resourceId) as newTas, groupResource as gr WHERE newTas.groupId = gr.groupId AND newTas.resource != gr.resourceId");
			while(result.next()){
				actualTas = new TASImpl(result.getInt(1), result.getInt(2),result.getInt(3),result.getInt(4));
				actualTas.setDirectTAS(false);
				tagAssignments.add(actualTas);	
				//nur (ungetaggte) resourcen koennen dazukommen 
				if(!resourceIdColumMapping.containsKey(actualTas.getResourceId())){
					resourceIdColumMapping.put(actualTas.getResourceId(), position);
					position++;
				}
			}
			//propagate tags of resources to their groups:
			result = sqlStatement.executeQuery("Select tas.userId, tas.tagId, g.groupId as resourceId, NULL as groupId FROM " +
						"(Select a.userId, a.tagId, a.resourceId from userTagGroupResource as a, Tag as t WHERE t.id = a.tagId) as tas, groupResource as g " +
							" WHERE g.resourceId = tas.resourceId");
			while(result.next()){
				actualTas = new TASImpl(result.getInt(1), result.getInt(2),result.getInt(3),result.getInt(4));
				actualTas.setDirectTAS(false);
				tagAssignments.add(actualTas);	
				//nur (ungetaggte) gruppen koennen dazukommen 
				if(!resourceIdColumMapping.containsKey(actualTas.getResourceId())){
					resourceIdColumMapping.put(actualTas.getResourceId(), position);
					position++;
				}
			}
			ObjectFactory.ds.getConnection().close();
			
			
			
			/* 2. Compute the Matrix: */
			
			//construct Matrix
			int numberOfVertices = userIdColumMapping.size() + tagIdColumMapping.size() + resourceIdColumMapping.size();
			adjacencyMatrix = new SparseDoubleMatrix2D(numberOfVertices,numberOfVertices);
			
			//fill adjacency matrix
			fillMatrixWithNormalTagAssignments(tagAssignments);
			
			//row-wise 1-Norm:
			computeRowWiseThe1Norm();
			
		}catch (SQLException e) {
			e.printStackTrace();
		}
		
	}
}
